package isquirrel;

import isquirrel.beans.YouTubeVideo;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Vector;

import com.google.gdata.client.Query;
import com.google.gdata.client.youtube.YouTubeQuery;
import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.Category;
import com.google.gdata.data.extensions.Rating;
import com.google.gdata.data.media.mediarss.MediaPlayer;
import com.google.gdata.data.media.mediarss.MediaThumbnail;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.data.youtube.VideoFeed;
import com.google.gdata.data.youtube.YouTubeMediaGroup;
import com.google.gdata.data.youtube.YouTubeNamespace;
import com.google.gdata.data.youtube.YtStatistics;
import com.google.gdata.util.ServiceException;

public class YouTubeWorker implements Runnable {

	private YouTubeService _service = null;
	private YouTubeQuery _query = null;
	
	private int page = 0;
	
	private String _keyword = null;
	private int _searchtype = 0;
	
	private YouTubeCollection _ytcollection = null;

	public YouTubeWorker(YouTubeService service, YouTubeCollection collection, String keyword, int searchType, int page){
		
		_service = service;
		_ytcollection = collection;
		_keyword = keyword;
		_searchtype = searchType;
		this.page = page;
		
	}
	
	private YouTubeVideo createYouTubeVideoObject(VideoEntry vid){
		
		YouTubeVideo ytvid = new YouTubeVideo(vid.getId().split(":")[3].toString(), vid.getTitle().getPlainText());
	    
		Rating rating = vid.getRating();
		if (rating != null){
			ytvid.setAvgRating(rating.getAverage());
		}
	
		YtStatistics stats = vid.getStatistics();
		if (stats != null){
			ytvid.setViewCount(stats.getViewCount());
		}
		
	    YouTubeMediaGroup mediaGroup = vid.getMediaGroup();
	    
	    for(MediaThumbnail mediaThumbnail : mediaGroup.getThumbnails()) {
	    	ytvid.thumbs().add(mediaThumbnail.getUrl());
	    }
	    
	    MediaPlayer mediaPlayer = mediaGroup.getPlayer();
	    if (mediaPlayer != null){
	    	ytvid.setPlayerUrl(mediaPlayer.getUrl());
	    }
		
		return ytvid;
	}
	
	private boolean initQuery(){
		
		try {
			_query = new YouTubeQuery(new URL("http://gdata.youtube.com/feeds/api/videos"));
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return false;
		}
		_query.setSafeSearch(YouTubeQuery.SafeSearch.MODERATE);
		_query.setMaxResults(12);
		_query.setOrderBy(YouTubeQuery.OrderBy.RELEVANCE);
		return true;
		
	}
		
	private void clearQuery(){
		_query = null;
	}
	
	private String toUrlString(String s){
		
		try {
			return URLEncoder.encode(s, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	public void run() {
	
		if(!initQuery()){
			_ytcollection.decrementWorkers();
			return;
		}
		
			
		Query.CategoryFilter filter = new Query.CategoryFilter();
		if (_searchtype == YouTubeAPI.AND_KEYWORDS){
			filter = new Query.CategoryFilter();
			filter.addCategory(new Category(YouTubeNamespace.KEYWORD_SCHEME, toUrlString(_keyword)));	
		}
		else if (_searchtype == YouTubeAPI.OR_KEYWORDS){
			filter.addCategory(new Category(YouTubeNamespace.KEYWORD_SCHEME, toUrlString(_keyword)));
		}
		_query.addCategoryFilter(filter);
	
		VideoFeed videoFeed = null;
		try {
			videoFeed = _service.query(_query, VideoFeed.class);
		} catch (IOException e) {
			_ytcollection.decrementWorkers();
			System.out.println(e.getMessage());
			return;

		} catch (ServiceException e) {
			_ytcollection.decrementWorkers();
			System.out.println(e.getMessage());
			return;
		}
				
		Vector<YouTubeVideo> videos = new Vector<YouTubeVideo>();
		while (page > 0){
			if (videoFeed.getNextLink() != null){
				try {
					videoFeed = _service.getFeed(new URL(videoFeed.getNextLink().getHref()), 
						       VideoFeed.class);
					--page;
				} catch (Exception e) {
					_ytcollection.decrementWorkers();
					System.out.println(e.getMessage());
					return;
				}
			}
			else{
				break;
			}
		}
		
		for(VideoEntry videoEntry : videoFeed.getEntries() ) {
			 videos.add(createYouTubeVideoObject(videoEntry));
		}
		
		_ytcollection.add(videos);
		_ytcollection.decrementWorkers();
		
		clearQuery();
		
	}

}
